package com.hxs.learn.service.core;

import java.io.Serializable;

import java.util.*;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;

import com.hxs.learn.common.entity.BillSequenceKey;
import com.hxs.learn.common.entity.TreeJson;
import com.hxs.learn.common.page.Page;
import com.hxs.learn.common.page.PageHelper;
import com.hxs.learn.common.page.PageWrapper;
import com.hxs.learn.common.result.Result;
import com.hxs.learn.common.web.LoginInfo;
import com.hxs.learn.constants.core.sql.SqlColConts;
import com.hxs.learn.entity.core.SysMenu;
import com.hxs.learn.entity.core.SysMenuPermission;
import com.hxs.learn.entity.core.SysRoleMenu;
import com.hxs.learn.entity.core.SysRoleMenuPermission;
import com.hxs.learn.mapper.core.SysMenuMapper;
import com.hxs.learn.mapper.core.SysMenuPermissionMapper;
import com.hxs.learn.mapper.core.SysRoleMenuMapper;
import com.hxs.learn.mapper.core.SysRoleMenuPermissionMapper;

/**
 * @author huxinsheng
 * @data 2018-04-24
 */
@Service
public class SysMenuService {
    private Logger                            logger = LoggerFactory.getLogger(SysUserService.class);
    private final SysMenuMapper               menuMapper;
    private final BillService                 billService;
    private final SysRoleMenuMapper           roleMenuMapper;
    private final SysRoleMenuPermissionMapper roleMenuPermissionMapper;
    private final SysMenuPermissionMapper     menuPermissionMapper;

    @Autowired
    public SysMenuService(SysMenuMapper menuMapper, BillService billService,
                          SysMenuPermissionMapper menuPermissionMapper, SysRoleMenuMapper roleMenuMapper,
                          SysRoleMenuPermissionMapper roleMenuPermissionMapper) {
        this.menuMapper               = menuMapper;
        this.billService              = billService;
        this.menuPermissionMapper     = menuPermissionMapper;
        this.roleMenuMapper           = roleMenuMapper;
        this.roleMenuPermissionMapper = roleMenuPermissionMapper;
    }

    private void buildMenuTreeGrid(List<SysMenu> menuModels, List<TreeJson<Object>> treeJsonList, String parentId) {
        if (!CollectionUtils.isEmpty(menuModels)) {
            for (SysMenu sysMenu : menuModels) {
                TreeJson treeJson = new TreeJson<SysMenu>();

                treeJson.setId(sysMenu.getId());
                treeJson.setPid(parentId);
                treeJson.setName(sysMenu.getName());
                treeJson.setData(sysMenu);
                treeJsonList.add(treeJson);

                List<SysMenu> subMenus = sysMenu.getSubMenus();

                if (!CollectionUtils.isEmpty(subMenus)) {
                    treeJson.set_children(true);
                    sysMenu.setSubMenus(null);
                    //buildMenuTreeGrid(subMenus, treeJsonList, sysMenu.getId());
                }
            }
        }
    }

    private void buildMenuTreeJson(List<SysMenu> menuModels, List<TreeJson<SysMenu>> treeJsonList) {
        for (SysMenu sysMenu : menuModels) {
            TreeJson<SysMenu> treeJson = new TreeJson<>();

            treeJson.setId(sysMenu.getId());
            treeJson.setName(sysMenu.getName());
            treeJson.setPid(sysMenu.getPid());
            treeJson.setData(sysMenu);

            if (!CollectionUtils.isEmpty(sysMenu.getSubMenus())) {
                List<SysMenu> subMenus = sysMenu.getSubMenus();
                sysMenu.setSubMenus(null);

                List<TreeJson<SysMenu>> subTreeJsons = new ArrayList<>();

                buildMenuTreeJson(subMenus, subTreeJsons);
                treeJson.setChildren(subTreeJsons);
            }

            treeJsonList.add(treeJson);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    void deleteChildMenus(Serializable id) {
        List<SysMenu> menuPojos = menuMapper.selectList(new EntityWrapper<SysMenu>().eq(SqlColConts.PID, id));

        if (!CollectionUtils.isEmpty(menuPojos)) {
            for (SysMenu menuPojo : menuPojos) {
                String menuId = menuPojo.getId();

                // 删除角色菜单权限关联数据
                Wrapper<SysRoleMenuPermission> rmpWrapper = new EntityWrapper<>();

                rmpWrapper.eq(SqlColConts.MENU_ID, menuId);
                roleMenuPermissionMapper.delete(rmpWrapper);

                // 删除角色菜单关联数据
                Wrapper<SysRoleMenu> rmWrapper = new EntityWrapper<>();

                rmWrapper.eq(SqlColConts.MENU_ID, menuId);
                roleMenuMapper.delete(rmWrapper);

                // 删除菜单权限关联数据
                Wrapper<SysMenuPermission> mpWrapper = new EntityWrapper<>();

                mpWrapper.eq(SqlColConts.MENU_ID, menuId);
                menuPermissionMapper.delete(mpWrapper);
                deleteChildMenus(menuId);
            }
        }
    }

    /**
     * 查询所有
     *
     * @return List<SysMenu>
     */
    public List<SysMenu> findAllSysMenu() {
        return menuMapper.selectList(new EntityWrapper<>(new SysMenu()));
    }

    /**
     * 按主键查询
     *
     * @param id 主键id
     * @return SysMenu
     */
    public SysMenu findById(Serializable id) {
        return menuMapper.selectById(id);
    }

    public SysMenu findByUrl(String path) {
        SysMenu menu = new SysMenu();

        menu.setUrl(path);

        return menuMapper.selectOne(menu);
    }

    public List<TreeJson<SysMenu>> findByUserId(String userId) {
        List<SysMenu>           menuModels   = menuMapper.findByUserIdAndParent(userId, SqlColConts.PID_VALUE);
        List<TreeJson<SysMenu>> treeJsonList = new ArrayList<>();

        buildMenuTreeJson(menuModels, treeJsonList);

        return treeJsonList;
    }

    /**
     * 分页查询
     *
     * @param page    分页对象
     * @param sysMenu 分页条件对象
     * @return PageWrapper<SysMenu>
     */
    public PageWrapper<SysMenu> findSysMenuPageData(Page page, SysMenu sysMenu) {
        return PageHelper.getPageData(menuMapper, page, sysMenu);
    }

    /**
     * 根据菜单名称查询系统菜单树数据
     *
     * @param sysMenu 菜单对象
     * @return
     */
    public List<TreeJson<Object>> findSysMenuTreeData(SysMenu sysMenu) {
        List<TreeJson<Object>> treeJsonList = new LinkedList<>();
        List<SysMenu>          menuModels   = menuMapper.selectByEntity(sysMenu);

        buildMenuTreeGrid(menuModels, treeJsonList, sysMenu.getPid());

        return treeJsonList;
    }

    /**
     * 按主键删除
     *
     * @param id        主键id
     * @param loginInfo 操作用户信息
     */
    @Transactional(rollbackFor = Exception.class)
    public Result removeById(LoginInfo loginInfo, Serializable id) {

        // 删除相应关联数据 删除角色菜单权限
        deleteChildMenus(id);

        // 删除角色菜单权限关联数据
        Wrapper<SysRoleMenuPermission> rmpWrapper = new EntityWrapper<>();

        rmpWrapper.eq(SqlColConts.MENU_ID, id);
        roleMenuPermissionMapper.delete(rmpWrapper);

        // 删除角色菜单关联数据
        Wrapper<SysRoleMenu> rmWrapper = new EntityWrapper<>();

        rmWrapper.eq(SqlColConts.MENU_ID, id);
        roleMenuMapper.delete(rmWrapper);

        // 删除菜单权限关联数据
        Wrapper<SysMenuPermission> mpWrapper = new EntityWrapper<>();

        mpWrapper.eq(SqlColConts.MENU_ID, id);
        menuPermissionMapper.delete(mpWrapper);

        // 删除子菜单
        menuMapper.delete(new EntityWrapper<SysMenu>().eq(SqlColConts.PID, id));

        // 删除本菜单
        menuMapper.deleteById(id);

        return Result.ok();
    }

    /**
     * 保存
     *
     * @param loginInfo 操作用户信息
     * @param sysMenu   系统菜单对象
     */
    @Transactional(rollbackFor = Exception.class)
    public Result save(LoginInfo loginInfo, SysMenu sysMenu) {
        sysMenu.setUpdateBy(loginInfo.getLoginName());
        sysMenu.setUpdateTime(new Date());

        Wrapper<SysMenu> wrapper = new EntityWrapper<>();

        if (StringUtils.isEmpty(sysMenu.getId())) {
            wrapper.eq(SqlColConts.NAME, sysMenu.getName());
        } else {
            wrapper.eq(SqlColConts.NAME, sysMenu.getName()).and().ne(SqlColConts.ID, sysMenu.getId());
        }

        int count = menuMapper.selectCount(wrapper);

        if (count > 0) {
            return Result.error("菜单名称已存在!");
        }

        if (StringUtils.isEmpty(sysMenu.getId())) {
            String id = billService.newBillNo(new BillSequenceKey(SqlColConts.KEY_MENU_ID));

            sysMenu.setId(id);
            sysMenu.setCreator(loginInfo.getLoginName());
            sysMenu.setCreateTime(new Date());
            menuMapper.insertAllColumn(sysMenu);
        } else {
            menuMapper.updateById(sysMenu);
        }

        return Result.ok();
    }
}


//~ Formatted by Jindent --- http://www.jindent.com
